using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using System.Collections.Generic;

using GSN.Config;

namespace GSN.Senders
{
    public class MagtifunSender : ISMSSender 
    {
        // properties read from configuration
        private string _username = null;
        private string _password = null;

        // others
        private CookieContainer _cookieJar = null;
        private Dictionary<string, string> _dictFormData = null;

        #region ISMSSender Members

        public void start()
        {
            Logger.log("Magtifun: Login...");
            // login
            _cookieJar = new CookieContainer();

            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://magtifun.ge/index.php?action=login");            
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";
            req.CookieContainer = _cookieJar;

            ASCIIEncoding a = new ASCIIEncoding();
            string postData = string.Format("login={0}&passwd={1}",
                _username.Substring(0, (16 < _username.Length ? 16 : _username.Length)),
                _password.Substring(0, (10 < _password.Length ? 10 : _password.Length)));

            byte[] bytes = a.GetBytes(postData);

            req.ContentLength = bytes.Length;

            Stream s = req.GetRequestStream();
            s.Write(bytes, 0, bytes.Length);
            s.Close();

            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Stream rs = resp.GetResponseStream();
            StreamReader reader = new StreamReader(rs);
            string responseStr = reader.ReadToEnd();
            reader.Close();
            rs.Close();
            resp.Close();

            bool loginSuccess = false;

            // check cookie jar for login success cookies
            if (_cookieJar.GetCookies(resp.ResponseUri)["njoySid"] != null &&
                        _cookieJar.GetCookies(resp.ResponseUri)["njoyLogin"] != null)
            {
                loginSuccess = true;
            }

            if (loginSuccess)
            {

                // read fields from response
                _dictFormData = new Dictionary<string, string>();
                _dictFormData["frommobile"] = null;
                _dictFormData["smscode"] = null;

                int keysFound = 0;

                Match m = Regex.Match(responseStr,
                                            @"<input\b[^>]*name=""?(.*?)[""|\s].*?value=""?(.*?)[""|\s].*?[/??|>]",
                                            RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
                while (m.Success)
                {
                    if (_dictFormData.ContainsKey(m.Groups[1].Value))
                    {
                        _dictFormData[m.Groups[1].Value] = m.Groups[2].Value;
                        ++keysFound;
                        if (keysFound == _dictFormData.Keys.Count)
                            break;
                    }


                    m = m.NextMatch();
                }

                Logger.log("Magtifun: Login Success.");

            }
            else
            {
                throw new Exception("MagtifunSender: Login Failed.");
            }

        }

        public void stop()
        {
            // logout
            Logger.log("Magtifun: Logout...");

            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://magtifun.ge/index.php?step=900");
            req.Method = "GET";
            req.ContentType = "application/x-www-form-urlencoded";
            // use cookies from login
            req.CookieContainer = _cookieJar;

            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            resp.Close();

            Logger.log("Magtifun: Logout Success.");

        }

        private int getPrefixCode(int prefix)
        {
            switch(prefix)
            {                
                case 899:
                    return 1;
                case 895:
                    return 6;
                case 891:
                    return 11;
                case 898:
                    return 5;
                case 896:
                    return 15;
                case 877:
                    return 2;
                case 893:
                    return 3;
                case 855:
                    return 7;
                case 858:
                    return 9;
                case 857:
                    return 14;
                case 897:
                    return 8;
                case 879:
                    return 10;
                case 871:
                    return 12;
                case 874:
                    return 13;
                default:
                    return 4;
            }
        }

        public void send(string recipient, string text)
        {

            Logger.log("Magtifun: Sending SMS...");
            

            // supports only up to 146 chars
            if (text.Length > 146)
                text = text.Remove(146);

            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://magtifun.ge/index.php?step=41");
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";
            // use cookies from login
            req.CookieContainer = _cookieJar;

            ASCIIEncoding a = new ASCIIEncoding();            

            // get recipient number prefix
            Match prefixMatch = Regex.Match(recipient, @"\d{3}");
            int prefix = int.Parse(prefixMatch.Value);
        
            string postData = string.Format(
                "frommobile={0}&smscode={1}&rawid=&jcode=&st=&code={2}&tomobile={3}&smstext={4}&returnstep=",
                _dictFormData["frommobile"],
                _dictFormData["smscode"],
                getPrefixCode(prefix),
                Uri.EscapeDataString(recipient),
                Uri.EscapeDataString(text));

            byte[] bytes = a.GetBytes(postData);

            req.ContentLength = bytes.Length;

            Stream s = req.GetRequestStream();
            s.Write(bytes, 0, bytes.Length);
            s.Close();

            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Stream rs = resp.GetResponseStream();
            StreamReader reader = new StreamReader(rs);
            string responseStr = reader.ReadToEnd();
            reader.Close();
            rs.Close();
            resp.Close();

            // somehow check if sent successfull
            if (responseStr.Contains("index.php?step=40&frommobile=") &&
                    responseStr.Contains("setTimeout"))
            {
                // successs!
                Logger.log("Magtifun: SMS Sent.");
            }
            else
            {
                // failed
                throw new Exception("Magtifun: SMS Failed.");
            }

        }

        public void load(GSN.Config.XmlPasswordNode node)
        {
            XmlPasswordNode n = node.SelectSingleNode("Username");
            if (n != null)
                _username = n.InnerText;

            n = node.SelectSingleNode("Password");
            if (n != null)
                _password = n.EncryptedInnerText;
        }

        public void save(GSN.Config.XmlPasswordWriter w)
        {
            w.WriteElementString("Username", _username);
            w.WritePasswordElementString("Password", _password);
        }

        #endregion

        #region IConfigurable Members

        public bool showConfigDialog(GSN.Config.IConfigurator configurator)
        {
            configurator.setItemString(_username, "Username");
            configurator.setItemString(_password, "Password");

            if (configurator.show())
            {
                _username = configurator.getItemString("Username");
                _password = configurator.getItemString("Password");

                return true;
            }

            return false;

        }

        public string getConfiguratorTypeName()
        {
            return "GSNConf.Senders.MagtifunSenderConfigurator";
        }

        #endregion

        public override bool Equals(object obj)
        {
            if (obj is ISMSSender)
            {
                if (obj is MagtifunSender)
                {
                    MagtifunSender s = (MagtifunSender)obj;
                    if (s._username == this._username &&
                            s._password == this._password)
                    {
                        return true;
                    }
                }
                else
                    return false;

            }

            return false;
        }

        public override int GetHashCode()
        {
            return (_username.GetHashCode() + _username.GetHashCode());
        }

        public override string ToString()
        {
            return "Magtifun.ge";
        }


    }
}
